﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace FCRE.helper
{
    /*
     .NET4.0下模拟.NET4.5已经实现的Task.Run及Task.Delay方法。
在.NET4.0下，有一个泛型类，叫TaskCompletionSource<TReuslt>，它能控制Task的行为，如给Task设置结果、设置异常、设置取消等。
         */
    class TaskEx
    {
        /// <summary>
        /// 执行委托action所代表的方法，并返回当前所表示的任务，因方法的签名返回值类型为Task，
        /// 所以需给tcs的SetResult方法设置一个null值。
        /// 使用方法：
        /// TaskEx.Run(() =>{...});
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        public static Task Run(Action action)
        {
            var tcs = new TaskCompletionSource<object>();
            new Thread(() => {
                try
                {
                    action();
                    tcs.SetResult(null);
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
            })
            { IsBackground = true }.Start();
            return tcs.Task;
        }
        /// <summary>
        /// 执行委托function所代表的方法，并返回当前所表示的任务，该任务类型为Task<TResut>，带有Task的返回值。
        /// 使用方法：
        /// string result = TaskEx.Run(() =>{...}).Result;
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="function"></param>
        /// <returns></returns>
        public static Task<TResult> Run<TResult>(Func<TResult> function)
        {
            var tcs = new TaskCompletionSource<TResult>();
            new Thread(() =>
            {
                try
                {
                    tcs.SetResult(function());
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
            })
            { IsBackground = true }.Start();
            return tcs.Task;
            //return Task.Factory.StartNew<TResult>(function);
        }
        /// <summary>
        /// 使用了System.Timers.Timer类来实现任务的延时，用来在milliSeconds毫秒后返回当前任务，该方法并不会阻塞任何线程。
        /// 使用方法：
        /// TaskEx.Delay(5000).Wait();
        /// </summary>
        /// <param name="milliseconds"></param>
        /// <returns></returns>
        public static Task Delay(int milliseconds)
        {
            var tcs = new TaskCompletionSource<object>();
            var timer = new System.Timers.Timer(milliseconds) { AutoReset = false };
            timer.Elapsed += delegate { timer.Dispose(); tcs.SetResult(null); };
            timer.Start();
            return tcs.Task;
        }
        /// <summary>
        /// 多线程调用(解决并发压力)
        /// </summary>
        /// <param name="func"></param>
        /// <returns></returns>
        //public static Task<JsonData> Run(Func<JsonData> func)
        //{
        //    return Run<JsonData>(func);
        //}

    }
}
